// Copyright  2012 Petr TALLA. [petr.talla@gmail.com]
// This file is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY;  without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
// [http://www.gnu.org/copyleft/lesser.html]
//=============================================================================
package tc.map;

import java.awt.Graphics;
import java.awt.Point;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;

//=============================================================================
public class TcMviewModel {
//=============================================================================
private final TcMview view;

private TcTileAddress center;
private Point centerOffset;

private final TcTileLoaderMediator mainToDispatchMediator;
private Map<String, TcTile> tiles = new HashMap<String, TcTile>();

public int tilesCountExt;

public TcMviewModel(TcMview view) {
	this.mainToDispatchMediator = new TcTileLoaderMediator(view);
	this.view = view;
	TcTileLoaderThread dispatch = new TcTileLoaderThread(mainToDispatchMediator);
	setCenter(1, 1, 1);
	centerOffset = new Point(0, 0);
	
	tilesCountExt = 0;
	if ( TcMviewControl.DEBUG_DRAWING ) tilesCountExt = -2;
	
	dispatch.start();
	
}

//=============================================================================
public TcTileAddress getCenterAddress () {
	return center;
}

public int getTilesCountHor() {
	int result = view.getWidth()/TcTile.TILE_PIXELS + 1;
	if (result < 2) result = 2;
	result += tilesCountExt;
	if (result < 2) result = 2;
	return result;
}

public int getTilesCountVer() {
	int result = view.getHeight()/TcTile.TILE_PIXELS + 1;
	if (result < 2) result = 2;
	result += tilesCountExt;
	if (result < 2) result = 2;
	return result;
}

public Point centerPoint() {
	return new Point(view.getWidth()/2, view.getHeight()/2);
}

public Point tileLeftTop(TcTileAddress tile)
{	int h = ( tile.getHor() - center.getHor() ) * 256 + centerOffset.x;
	int v = ( tile.getVer() - center.getVer() ) * 256 + centerOffset.y;
	Point c = centerPoint();
		
	return new Point(c.x+h, c.y+v);
}

public void zoomin() { 
	if ( center.getLayer() == TcTileAddress.LAYER_MAX ) return;
	setCenter(center.getLayer()+1, center.getHor()*2, center.getVer()*2);
	int h = centerOffset.x;
	int v = centerOffset.y;
	centerOffset.x = 0;
	centerOffset.y = 0;
	moveCenter(h*2, v*2);
}

public void zoomout() { 
	if ( center.getLayer() == TcTileAddress.LAYER_MIN ) return;
	setCenter(center.getLayer()-1, center.getHor()/2, center.getVer()/2);
	int h = centerOffset.x;
	int v = centerOffset.y;
	centerOffset.x = 0;
	centerOffset.y = 0;
}

public void moveCenter(int horPix, int verPix) {
	horPix += centerOffset.x;
	verPix += centerOffset.y;
	
	centerOffset.x = horPix%256;
	centerOffset.y = verPix%256;
	
	setCenter(center.getLayer(), center.getHor()-horPix/256, center.getVer()-verPix/256);
}

public void setCenter(int layer, int hor, int ver )
{	center = new TcTileAddress(layer, hor, ver);

	int max = TcTileAddress.maxHorVer(layer);
	int dHor = getTilesCountHor()/2;
	int dVer = getTilesCountVer()/2;
	int horFrom = hor - dHor-2; if ( horFrom < 0   ) horFrom = 0;
	int horTo   = hor + dHor+2; if ( horTo > max ) horTo = max; 
	int verFrom = ver - dVer-3; if ( verFrom < 0     ) verFrom = 0;
	int verTo   = ver + dVer+1; if ( verTo > max   ) verTo = max;
	
	for ( int h = horFrom; h <= horTo; h++ ) {
		for ( int v = verFrom; v <= verTo; v++ ) {
			TcTileAddress address = new TcTileAddress(layer, h, v);	
			String key = address.toString();
			if ( tiles.containsKey(key) ) continue;
			TcTile tile = new TcTile(layer, h, v);
			tiles.put(key, tile);
			mainToDispatchMediator.appendTile(tile);
		}
	}
	
	mainToDispatchMediator.updateCenter(center);
}

public void draw( Graphics g)
{	Iterator<TcTile> ti = tiles.values().iterator();

	while (ti.hasNext())
	{	TcTile tile = ti.next();
		if ( tile.getAddress().getLayer() != center.getLayer() ) continue;
		Point lt = tileLeftTop(tile.getAddress());
		tile.draw(g, lt.x, lt.y, center.getHor(), center.getVer());			
	}
	
	if ( TcMviewControl.DEBUG_DRAWING == false ) return;
	
	int h = view.getWidth()/2;
	int v = view.getHeight()/2;
	
	g.drawLine(h-30, v-30, h+30, v+30);
	g.drawLine(h+30, v-30, h-30, v+30);
	g.drawOval(h-10, v-10, 20, 20);
	
	String offset;
	g.drawString(String.format("[%d, %d]", centerOffset.x, centerOffset.y), h+15, v-15);
}
//=============================================================================
}






